﻿using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;
using System.Text;
using SharePointAccelerators.Common;

namespace SharePointAccelerators.EmailArchive.EmailEventReceiver
{
    /// <summary>
    /// List Email Events
    /// </summary>
    public class EmailEventReceiver : SPEmailEventReceiver
    {
        enum LookForEnum
        {
            Year,
            Month,
            Day
        }


       /// <summary>
       /// The list received an e-mail message.
       /// </summary>
       public override void EmailReceived(SPList list, SPEmailMessage emailMessage, String receiverData)
       {
           try
           {
               SharePointAccelerators.Common.LoggingService.LogError(CategoriesEnum.Acceleratio, list.Title);

               SPFolder storageFolder = GetFolder(list, DateTime.Now);

               string subject = emailMessage.Headers["Subject"];
               SharePointAccelerators.Common.LoggingService.LogError(CategoriesEnum.Acceleratio, subject);


               string urlSlug = GenerateSlug(subject, 255 - storageFolder.ServerRelativeUrl.Length - 40);
               SPWeb web = list.ParentWeb;

               if (urlSlug == "" || web.GetFolder(storageFolder.ServerRelativeUrl + "/" + urlSlug).Exists)
               {
                   urlSlug = string.Format("{0}-{1}", urlSlug, Guid.NewGuid());
               }

               SPFolder emailFolder = storageFolder.SubFolders.Add(storageFolder.ServerRelativeUrl + "/" + urlSlug);

               //SaveEmail(emailFolder, subject, emailMessage.GetMessageStream());

               SPEmailAttachmentCollection attachColl = emailMessage.Attachments;
               foreach (SPEmailAttachment attach in attachColl)
               {
                   AddFileToFolder(emailFolder, attach, attach.FileName, subject);
               }
           }
           catch (Exception ex)
           {
               SharePointAccelerators.Common.LoggingService.LogException(SharePointAccelerators.Common.CategoriesEnum.Acceleratio, ex);
           }
       }

       private void SaveEmail(SPFolder ParentFolder, string Subject, Stream Message)
       {
           string filename = string.Format(@"{0}.eml", Subject);

           byte[] binaryContent = null;
           String mailContent = String.Empty;

           AddFileToFolder(ParentFolder, Message, filename, Subject);
       }

       private void AddFileToFolder(SPFolder Folder, SPEmailAttachment attach, string filename, string Subject)
       {
           AddFileToFolder(Folder, attach.ContentStream, filename, Subject);
       }

       private void AddFileToFolder(SPFolder Folder, System.IO.Stream File, string FileName, string Subject)
       {
           string filename = GetUniqueFileName(FileName, Folder, Folder.ParentWeb);

           SPFile file = Folder.Files.Add(Folder.ServerRelativeUrl + "/" + filename, File);
           file.Item["Subject"] = Subject;
           file.Item.SystemUpdate();
       }

       private string GenerateSlug(string phrase, int maxLength)
       {
           string str = phrase.ToLower();

           str = Regex.Replace(str, @"dž", "dj");
           str = Regex.Replace(str, @"ž", "z");
           str = Regex.Replace(str, @"č", "c");
           str = Regex.Replace(str, @"ć", "c");
           str = Regex.Replace(str, @"š", "s");

           // invalid chars, make into spaces
           str = Regex.Replace(str, @"[^a-z0-9\s-]", "");
           // convert multiple spaces/hyphens into one space       
           str = Regex.Replace(str, @"[\s-]+", " ").Trim();
           // hyphens
           str = Regex.Replace(str, @"\s", "-");

           // cut and trim it
           str = str.Substring(0, str.Length <= maxLength ? str.Length : maxLength).Trim();

           return str;
       }

       private SPFolder GetFolder(SPList DocumentLibrary, DateTime DateReceived)
       {
           return GetFolder(DocumentLibrary.ParentWeb, DocumentLibrary.RootFolder, DateReceived, LookForEnum.Year);
       }

       private SPFolder GetFolder(SPWeb Web, SPFolder ParentFolder, DateTime DateReceived, LookForEnum LookFor)
       {
           switch (LookFor)
           {
               case LookForEnum.Year:
                   SPFolder yearFolder = GetFolder(Web, ParentFolder, DateReceived.Year.ToString(), false);
                   return GetFolder(Web, yearFolder, DateReceived, LookForEnum.Month);
               case LookForEnum.Month:
                   DateTimeFormatInfo fmt = (new CultureInfo((int)Web.RegionalSettings.LocaleId)).DateTimeFormat;
                   SPFolder monthFolder = GetFolder(Web, ParentFolder, DateReceived.ToString("MM-MMMM", fmt), false);
                   return GetFolder(Web, monthFolder, DateReceived, LookForEnum.Day);
               case LookForEnum.Day:
                   return GetFolder(Web, ParentFolder, DateReceived.ToString("dd"), false);
               default:
                   return null;
           }
       }

       private string GetUniqueFileName(string FileName, SPFolder ParentFolder, SPWeb Web)
       {
           if (Web.GetFile(ParentFolder.ServerRelativeUrl + "/" + FileName).Exists)
           {
               return string.Format("{0}-{1}.{2}", Path.GetFileName(FileName), Guid.NewGuid(), Path.GetExtension(FileName));
           }
           else
           {
               return FileName;
           }
       }

       private SPFolder GetFolder(SPWeb Web, SPFolder ParentFolder, string LookForValue, bool Unique)
       {
           string subfolderUrl = UrlOfFolder(ParentFolder.ServerRelativeUrl, LookForValue);

           if (!Unique)
           {
               if (!Web.GetFolder(subfolderUrl).Exists)
               {
                   return ParentFolder.SubFolders.Add(subfolderUrl);
               }
               else
               {
                   return Web.GetFolder(UrlOfFolder(ParentFolder.ServerRelativeUrl, LookForValue));
               }
           }
           else
           {
               if (!Web.GetFolder(subfolderUrl).Exists)
               {
                   return ParentFolder.SubFolders.Add(subfolderUrl);
               }

               int i = 0;
               while (Web.GetFolder(string.Format("{0}-{1}", subfolderUrl, i.ToString())).Exists)
               { 
                    i++;
               }

               return ParentFolder.SubFolders.Add(string.Format("{0}-{1}", subfolderUrl, i.ToString()));
           }
       }

       private string UrlOfFolder(string ParentPath, string TopicNumber)
       {
           return ParentPath + "/" + TopicNumber;
       }
    }
}
